home *** CD-ROM | disk | FTP | other *** search
- /*
- * gc.c
- *
- * Great Circle. This program is used to determine bearing
- * and range to two stations given latitude and longitude.
- *
- * Ver 1.04 By S. R. Sampson, N5OWK
- * Public Domain (p) April 1991
- *
- * Ref: Air Force Manual 51-40, "Air Navigation", 1 February 1987
- *
- * Usage examples:
- *
- * gc 35.19n97.27w 0s0e (Moore to Prime/Equator)
- * gc 35.19N97.27W 38.51n77.02W (Moore to Washington D.C.)
- * gc 33.56n118.24w 55.45n37.35e (L.A. to Moscow U.S.S.R.)
- * gc 35N70W 35N71W (No decimal points used)
- */
-
- /* Includes */
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
-
- /* Defines */
-
- #define RADIAN (180.0 / M_PI)
-
- /* Simple Declare, No Prototypes */
-
- /*
- * Error routine
- */
-
- void err(type)
- int type;
- {
- switch(type) {
- case 1:
- printf("\007Latitude Out of Range (90N to 90S)\n");
- break;
- case 2:
- printf("\007Longitude Out of Range (180W to 180E)\n");
- break;
- case 3:
- printf("\007Minutes Out of Range (0 to 59)\n");
- }
-
- exit(1);
- }
-
- /*
- * Convert Degrees and Minutes to Decimal
- */
-
- double dm2dec(n)
- double n;
- {
- double t;
-
- t = (int)n;
- n -= t;
- n /= .60;
-
- if (n >= 1.0)
- err(3);
-
- return (n + t);
- }
-
- /*
- * Parse the input line
- *
- * dd(.mm)[NnSs]ddd(.mm)[EeWw]
- */
-
- void parse(s, lat, lon)
- char *s;
- double *lat, *lon;
- {
- register char *i, *t;
- int l;
-
- l = strlen(s);
- for (i = s; i < (s + l); ++i) {
- switch(toupper(*i)) {
- case 'N':
- *i = '\0';
- t = i + 1;
- *lat = atof(s);
- break;
- case 'S':
- *i = '\0';
- t = i + 1;
- *lat = -atof(s);
- break;
- case 'E':
- *i = '\0';
- *lon = -atof(t);
- break;
- case 'W':
- *i = '\0';
- *lon = atof(t);
- }
- }
-
- *lat = dm2dec(*lat);
- *lon = dm2dec(*lon);
-
- if (*lat > 90.0 || *lat < -90.0)
- err(1);
-
- if (*lon > 180.0 || *lon < -180.0)
- err(2);
-
- /* Prevent ACOS() Domain Error */
-
- if (*lat == 90.0)
- *lat = 89.9;
-
- if (*lat == -90.0)
- *lat = -89.9;
- }
-
- void main(argc, argv)
- int argc;
- char **argv;
- {
- double x, y, tmp, dist, range, TO_Bearing, FROM_Bearing;
- double QTH_Lat, QTH_Long, DEST_Lat, DEST_Long, Delta_Long;
-
- if (argc != 3) {
- printf("Usage: gc station1 station2\n\n" \
- "This program computes Great Circle Bearing and Range\n" \
- "given the latitude and longitude (degrees and minutes).\n\n" \
- "You must input the lat/long of the two stations.\n" \
- "The output will then be relative from station1 to station2.\n\n" \
- "Input the two station lat/longs using the following format:\n\n" \
- "\tdd.mmHddd.mmG lead/lagging zeros can be left out.\n\n" \
- "d = Degrees, m = Minutes, H = Hemisphere (N or S), " \
- "G = Greenwich (W or E)\n");
-
- exit(1);
- }
-
- /* Process the command line data */
-
- parse(argv[1], &QTH_Lat, &QTH_Long);
- parse(argv[2], &DEST_Lat, &DEST_Long);
-
- /* Compute the Bearing and Range, From the Formula in Chapter 23 */
-
- Delta_Long = DEST_Long - QTH_Long;
-
- QTH_Lat /= RADIAN; /* Convert variables to Radians */
- QTH_Long /= RADIAN;
- DEST_Lat /= RADIAN;
- Delta_Long /= RADIAN;
-
- tmp = (sin(QTH_Lat) * sin(DEST_Lat)) +
- (cos(QTH_Lat) * cos(DEST_Lat) * cos(Delta_Long));
-
- dist = acos(tmp);
- range = 60.0 * (dist * RADIAN); /* change to nautical miles */
-
- x = (sin(DEST_Lat) - (sin(QTH_Lat) * cos(dist))) /
- (sin(dist) * cos(QTH_Lat));
-
- y = (sin(QTH_Lat) - (sin(DEST_Lat) * cos(dist))) /
- (sin(dist) * cos(DEST_Lat));
-
- x = acos(x) * RADIAN; /* change to degrees */
- y = acos(y) * RADIAN;
-
- if (DEST_Long > QTH_Long) {
- TO_Bearing = 360.0 - x;
- FROM_Bearing = y;
- } else {
- TO_Bearing = x;
- FROM_Bearing = 360.0 - y;
- }
-
- /* Computations complete, show answer */
-
- printf("\n TO Bearing is %03.0f Degrees for %.0f Nautical Miles\n",
- TO_Bearing, range);
- printf("FROM Bearing is %03.0f Degrees\n", FROM_Bearing);
-
- exit(0);
- }
-
- /* EOF */
-